Welcome to Bluetooth Section

Build a connection between Arduino and Your Laptop!

Start scrolling!

Objective

The purpose of part two of this lab is to establish communication between your computer and the Artemis board through the Bluetooth stack. We will be using Python inside a Jupyter notebook on the computer end and the Arduino programming language on the Artemis side. We will also establish a framework for sending data via Bluetooth that will be useful in future labs.

  • Connect Arduino with out laptop.
  • Data interaction between two devices.
  • Call back function and notification handler.
  • Timestamps combined with temperature data.

Pre lab

We can get the MAC Address using the code below, the result MAC Address is shown in the serial monitor.

Description of the image

Task 1

Send an ECHO command with a string value from the computer to the Artemis board, and receive an augmented string on the computer.

We can see from the figure below that after sending a command 'ECHO' with a text 'hello', the Arduino returned a sentence 'The Robot says -> hello' in the serial monitor.

Description of the image

The corresponding code is show below

                        
            case ECHO:

            char char_arr[MAX_MSG_SIZE];

            // Extract the next value from the command string as a character array
            success = robot_cmd.get_next_value(char_arr);
            if (!success){
                Serial.print("Not Success!");
                return;
            }
                

            tx_estring_value.clear();
            tx_estring_value.append("The Robot says -> ");
            tx_estring_value.append(char_arr);
            tx_characteristic_string.writeValue(tx_estring_value.c_str());

            Serial.print("Sent back: ");
            Serial.println(tx_estring_value.c_str());
            
            break;
                        
                        

Task 2

Add a command GET_TIME_MILLIS which makes the robot reply write a string such as “T:123456” to the string characteristic.

We can see from the figure below that after sending a command 'GET_TIME_MILLIS', the Arduino returned a string 'T:123456' in the serial monitor.

Description of the image

The corresponding code is show below

                        
            case GET_TIME_MILLIS:
            tx_estring_value.clear();
            tx_estring_value.append("T:123456");
            tx_characteristic_string.writeValue(tx_estring_value.c_str());

            Serial.print("Sent back: ");
            Serial.println(tx_estring_value.c_str());
            break;
                        
                        

Task 3

Setup a notification handler in Python to receive the string value (the BLEStringCharactersitic in Arduino) from the Artemis board. In the callback function, extract the time from the string.

Here below is the instruction of the function we gonna use in implementing the notification handler callback function

Description of the image

Let's take a look at the source code of the function start_notify() and stop_notify in the figure below:

Description of the image

And the function of converting bytearray to string/float/int :

Description of the image

combining the function above, we can wrote the code below in our Jupyter Notebook:

                            
            def handle_notification(uuid,bytearray):
            converted_num = ble.bytearray_to_float(bytearray)
            print('The current time is : ',converted_num)
        
            ble.start_notify(ble.uuid['RX_FLOAT'],handle_notification)
            
            time.sleep(3)
            
            ble.stop_notify(ble.uuid['RX_FLOAT'])
                            
                            

And then get the result:

Description of the image

As shown above, our computer successfully handled the notification sent from the Arduino

Task 4

Write a loop that gets the current time in milliseconds and sends it to your laptop to be received and processed by the notification handler. Collect these values for a few seconds and use the time stamps to determine how fast messages can be sent. What is the effective data transfer rate of this method?

Here below is the code written in the Arduino

                            
            case HOW_FAST:
            cnt=0;
            while(cnt < MAX_STRING)
            {
                tx_estring_value.clear();
                tx_estring_value.append("T:");
                tx_estring_value.append((float)millis());
                tx_characteristic_string.writeValue(tx_estring_value.c_str());
                cnt++;
            }
            break;
                            
                        

Some IMPORTANT notes:

  • Here we used the estring to transmit the timestamps instead of the float value
  • This is to avoid conflict with the write_data() function in main loop
  • Also, the estring is more general to use because it can be adapted to string/int/float types of values
  • the value of millis() is long, so we have to convert it using '(float)'

Then we can implement the callback function in Jupyter Notebook to receive information from Arduino

Description of the image

To make the timestamps results shown in the figure above easier to analyze, we made line-plots below:

Description of the image

Description of the image

As shown above, the time interval in this approach is unstable, the difference is 0ms or about 60ms

By further caculating the data from the time interval, we get the result:

Description of the image

Task 5

Now create an array that can store time stamps. This array should be defined globally so that other functions can access it if need be. In the loop, rather than send each time stamp, place each time stamp into the array. (Note: you’ll need some extra logic to determine when your array is full so you don’t “over fill” the array.) Then add a command SEND_TIME_DATA which loops the array and sends each data point as a string to your laptop to be processed. (You can store these values in a list in python to determine if all the data was sent over.)

To store the data in the array, we use the code below in the Arduino:

Description of the image

And the results in the Jupyter Notebook is shown below:

Description of the image

The line-plot based on this data is:

Description of the image

Description of the image

And the analyzed data is:

Description of the image

Discussion:

This approach is much more stable since the time difference is almost 0 with seldom fluctuate, and the standard deviation of the time difference is also much smaller than that of the last approach

Task 6

Add a second array that is the same size as the time stamp array. Use this array to store temperature readings. Each element in both arrays should correspond, e.e., the first time stamp was recorded at the same time as the first temperature reading. Then add a command GET_TEMP_READINGS that loops through both arrays concurrently and sends each temperature reading with a time stamp. The notification handler should parse these strings and add populate the data into two lists.

Here below is the code in Arduino, which can store and send both the timestamps and temperature:

Description of the image

Here we used the command float temp_f = getTempDegF() to get the temperature data from Arduino

And the received result in the Jupyter Notebook is shown below:

Description of the image

The result shows that the time and temperature data are well received and separared in my laptop

Task 7

Discuss the differences between these two methods, the advantages and disadvantages of both and the potential scenarios that you might choose one method over the other. How “quickly” can the second method record data? The Artemis board has 384 kB of RAM. Approximately how much data can you store to send without running out of memory?

Discussion:

The first method is sending information immidiately after gasping the data from the Arduino, whose data transfer time interval is relatively unstable, and this method do not require much on the RAM.

The second method is storing data in the array and then read and transfer the data from the Arduino to the computer, which is much more stable but needs more RAM space to operate.

For the second approach, if we are sampling data at 1 kHz and each sample is 4 bytes (32 bits), we would be storing data at a rate of 4 kilobytes per second (1 kHz * 4 bytes). The 384kB RAM could be filled up in 96 seconds (384 kB / 4 kB per second).

Additional Task 1

Effective Data Rate And Overhead: Send a message from the computer and receive a reply from the Artemis board. Note the respective times for each event, calculate the data rate for 5-byte replies and 120-byte replies. Do many short packets introduce a lot of overhead? Do larger replies help to reduce overhead? You may also test additional reply sizes. Please include at least one plot to support your write-up.

Here below is the code of sending messages.

Description of the image

Here below is the code of receiving and replying the message.

Description of the image

After testing, the 5-byte rate is 21.05 bytes/sec, and the 120-byte rate is 517.28 bytes/sec

The graph below illustrates a clear correlation between the data rate and the quantity of bytes transmitted. This pattern indicates that sending larger replies contributes to a reduction in overhead.

Description of the image

Additional Task 2

Reliability: What happens when you send data at a higher rate from the robot to the computer? Does the computer read all the data published (without missing anything) from the Artemis board? Include your answer in the write-up.

To test the Reliability in high-speed transfer, we print the result of the function SEND_TIME_DATA in both Arduino and Jupyter lab, here below is the results:

Description of the image

We could notice that the transfer rate is very high and the lost of data did not occur, which implys that this system has a good Reliability